/*
 * SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
 *
 * SPDX-License-Identifier: MulanPSL-2.0
 */
#![allow(
    dead_code,
    mutable_transmutes,
    non_camel_case_types,
    non_snake_case,
    non_upper_case_globals,
    unused_assignments,
    unused_mut,
    unused_variables,
    clashing_extern_declarations,
    clippy::never_loop,
    clippy::absurd_extreme_comparisons
)]
use crate::common::*;

#[link(name = "audit")]
#[link(name = "pam")]
#[link(name = "ldap")]
#[link(name = "lber")]
#[link(name = "z")]
#[link(name = "util_variadic")]
#[link(name = "plugins_variadic")]
extern "C" {
    fn setrlimit(__resource: __rlimit_resource_t, __rlimits: *const rlimit) -> libc::c_int;
    fn getrlimit(__resource: __rlimit_resource_t, __rlimits: *mut rlimit) -> libc::c_int;
    fn fclose(__stream: *mut FILE) -> libc::c_int;
    fn fopen(_: *const libc::c_char, _: *const libc::c_char) -> *mut FILE;
    fn fgetc(__stream: *mut FILE) -> libc::c_int;
    fn rewind(__stream: *mut FILE);
    fn fileno(__stream: *mut FILE) -> libc::c_int;
    fn malloc(_: libc::c_ulong) -> *mut libc::c_void;
    fn calloc(_: libc::c_ulong, _: libc::c_ulong) -> *mut libc::c_void;
    fn reallocarray(__ptr: *mut libc::c_void, __nmemb: size_t, __size: size_t)
        -> *mut libc::c_void;
    fn free(_: *mut libc::c_void);
    fn memcpy(_: *mut libc::c_void, _: *const libc::c_void, _: libc::c_ulong) -> *mut libc::c_void;
    fn memset(_: *mut libc::c_void, _: libc::c_int, _: libc::c_ulong) -> *mut libc::c_void;
    fn strcmp(_: *const libc::c_char, _: *const libc::c_char) -> libc::c_int;
    fn strncmp(_: *const libc::c_char, _: *const libc::c_char, _: libc::c_ulong) -> libc::c_int;
    fn strdup(_: *const libc::c_char) -> *mut libc::c_char;
    fn strndup(_: *const libc::c_char, _: libc::c_ulong) -> *mut libc::c_char;
    fn strchr(_: *const libc::c_char, _: libc::c_int) -> *mut libc::c_char;
    fn strrchr(_: *const libc::c_char, _: libc::c_int) -> *mut libc::c_char;
    fn strlen(_: *const libc::c_char) -> libc::c_ulong;
    fn close(__fd: libc::c_int) -> libc::c_int;
    fn geteuid() -> __uid_t;
    fn __errno_location() -> *mut libc::c_int;
    fn open(__file: *const libc::c_char, __oflag: libc::c_int, _: ...) -> libc::c_int;
    fn fcntl(__fd: libc::c_int, __cmd: libc::c_int, _: ...) -> libc::c_int;
    fn getaddrinfo(
        __name: *const libc::c_char,
        __service: *const libc::c_char,
        __req: *const addrinfo,
        __pai: *mut *mut addrinfo,
    ) -> libc::c_int;
    fn freeaddrinfo(__ai: *mut addrinfo);
    fn __ctype_b_loc() -> *mut *const libc::c_ushort;
    fn init_parser(path: *const libc::c_char, quiet: bool) -> bool;
    fn sudo_warn_set_locale_func_v1(
        func: Option<unsafe extern "C" fn(bool, *mut libc::c_int) -> bool>,
    );
    fn sudo_warn_nodebug_v1(fmt: *const libc::c_char, _: ...);
    fn sudo_warnx_nodebug_v1(fmt: *const libc::c_char, _: ...);
    fn init_defaults() -> bool;
    fn update_defaults(
        parse_tree: *mut sudoers_parse_tree,
        defs: *mut defaults_list,
        what: libc::c_int,
        quiet: bool,
    ) -> bool;
    static mut sudo_defs_table: [sudo_defs_types; 0];
    fn setlocale(__category: libc::c_int, __locale: *const libc::c_char) -> *mut libc::c_char;
    fn sudoers_warn_setlocale(restore: bool, cookie: *mut libc::c_int) -> bool;
    fn sudoers_setlocale(newlocale: libc::c_int, prevlocale: *mut libc::c_int) -> bool;
    fn audit_success(argc: libc::c_int, argv: *mut *mut libc::c_char) -> libc::c_int;
    fn audit_failure(
        argc: libc::c_int,
        argv: *mut *mut libc::c_char,
        fmt: *const libc::c_char,
        _: ...
    ) -> libc::c_int;
    fn log_allowed(status: libc::c_int) -> bool;
    fn log_denial(status: libc::c_int, inform_user: bool) -> bool;
    fn log_failure(status: libc::c_int, flags: libc::c_int) -> bool;
    fn log_warning(flags: libc::c_int, fmt: *const libc::c_char, _: ...) -> bool;
    fn log_warningx(flags: libc::c_int, fmt: *const libc::c_char, _: ...) -> bool;
    fn gai_log_warning(
        flags: libc::c_int,
        errnum: libc::c_int,
        fmt: *const libc::c_char,
        _: ...
    ) -> bool;
    fn sudoers_initlocale(ulocale: *const libc::c_char, slocale: *const libc::c_char) -> bool;
    fn sudoers_locale_callback(_: *const sudo_defs_val) -> bool;
    fn sudoers_lookup(
        snl_0: *mut sudo_nss_list,
        pw: *mut passwd,
        validated: libc::c_int,
        pwflag: libc::c_int,
    ) -> libc::c_int;
    fn display_privs(snl_0: *mut sudo_nss_list, pw: *mut passwd, verbose: bool) -> libc::c_int;
    fn display_cmnd(snl_0: *mut sudo_nss_list, pw: *mut passwd) -> libc::c_int;
    fn sudo_read_nss() -> *mut sudo_nss_list;
    fn sudo_secure_file_v1(
        path: *const libc::c_char,
        uid: uid_t,
        gid: gid_t,
        sbp: *mut stat,
    ) -> libc::c_int;
    fn sudo_strtoid_v2(str: *const libc::c_char, errstr: *mut *const libc::c_char) -> id_t;
    fn sudo_debug_printf2_v1(
        func: *const libc::c_char,
        file: *const libc::c_char,
        line: libc::c_int,
        level: libc::c_int,
        fmt: *const libc::c_char,
        _: ...
    );
    static mut sudoers_subsystem_ids: [libc::c_uint; 0];
    fn find_path(
        infile: *const libc::c_char,
        outfile: *mut *mut libc::c_char,
        sbp: *mut stat,
        path: *const libc::c_char,
        ignore_dot: libc::c_int,
        whitelist: *const *mut libc::c_char,
    ) -> libc::c_int;
    fn check_user(validate: libc::c_int, mode: libc::c_int) -> libc::c_int;
    fn check_user_shell(pw: *const passwd) -> bool;
    fn user_is_exempt() -> bool;
    fn rewind_perms() -> bool;
    fn set_perms(_: libc::c_int) -> bool;
    fn restore_perms() -> bool;
    static mut sudoers_file: *const libc::c_char;
    static mut sudoers_mode: mode_t;
    static mut sudoers_uid: uid_t;
    static mut sudoers_gid: gid_t;
    fn sudo_getgrgid(_: gid_t) -> *mut group;
    fn sudo_getgrnam(_: *const libc::c_char) -> *mut group;
    fn sudo_gr_delref(_: *mut group);
    fn sudo_fakegrnam(_: *const libc::c_char) -> *mut group;
    fn sudo_get_gidlist(pw: *const passwd, type_0: libc::c_uint) -> *mut gid_list;
    fn sudo_fakepwnam(_: *const libc::c_char, _: gid_t) -> *mut passwd;
    fn sudo_mkpwent(
        user: *const libc::c_char,
        uid: uid_t,
        gid: gid_t,
        home: *const libc::c_char,
        shell: *const libc::c_char,
    ) -> *mut passwd;
    fn sudo_getpwnam(_: *const libc::c_char) -> *mut passwd;
    fn sudo_getpwuid(_: uid_t) -> *mut passwd;
    fn sudo_freegrcache();
    fn sudo_freepwcache();
    fn sudo_pw_delref(_: *mut passwd);
    fn cb_maxseq(sd_un: *const sudo_defs_val) -> bool;
    fn cb_iolog_user(sd_un: *const sudo_defs_val) -> bool;
    fn cb_iolog_group(sd_un: *const sudo_defs_val) -> bool;
    fn cb_iolog_mode(sd_un: *const sudo_defs_val) -> bool;
    fn expand_iolog_path(
        prefix: *const libc::c_char,
        dir: *const libc::c_char,
        file: *const libc::c_char,
        slashp: *mut *mut libc::c_char,
    ) -> *mut libc::c_char;
    fn env_get() -> *mut *mut libc::c_char;
    fn env_swap_old() -> bool;
    fn env_init(envp: *const *mut libc::c_char) -> bool;
    fn insert_env_vars(envp: *const *mut libc::c_char) -> bool;
    fn read_env_file(path: *const libc::c_char, overwrite: bool, restricted: bool) -> bool;
    fn rebuild_env() -> bool;
    fn validate_env_vars(envp: *const *mut libc::c_char) -> bool;
    fn sudo_fatal_callback_register_v1(func: sudo_fatal_callback_t) -> libc::c_int;
    fn sudo_strlcpy(dst: *mut libc::c_char, src: *const libc::c_char, siz: size_t) -> size_t;
    fn bindtextdomain(
        __domainname: *const libc::c_char,
        __dirname: *const libc::c_char,
    ) -> *mut libc::c_char;
    fn sudoers_policy_exec_setup(
        argv: *mut *mut libc::c_char,
        envp: *mut *mut libc::c_char,
        cmnd_umask: mode_t,
        iolog_path: *mut libc::c_char,
        v: *mut libc::c_void,
    ) -> libc::c_int;
    fn sudoers_policy_deserialize_info(
        v: *mut libc::c_void,
        runas_user_0: *mut *mut libc::c_char,
        runas_group_0: *mut *mut libc::c_char,
    ) -> libc::c_int;
    fn group_plugin_unload();
    fn cb_group_plugin(sd_un: *const sudo_defs_val) -> bool;
    fn find_editor(
        nfiles: libc::c_int,
        files: *mut *mut libc::c_char,
        argc_out: *mut libc::c_int,
        argv_out: *mut *mut *mut libc::c_char,
        whitelist: *const *mut libc::c_char,
        env_editor: *mut *const libc::c_char,
        env_error: bool,
    ) -> *mut libc::c_char;
}

pub const SETDEF_GENERIC: libc::c_int = 0x01;
pub const SETDEF_HOST: libc::c_int = 0x02;
pub const SETDEF_USER: libc::c_int = 0x04;
pub const SETDEF_RUNAS: libc::c_int = 0x08;
pub const SLOG_NO_STDERR: libc::c_int = 0x10;
pub const PERM_INITIAL: libc::c_int = 0x00;
pub const NOT_FOUND_ERROR: libc::c_int = 3;
pub const FLAG_NO_USER: libc::c_int = 0x020;
pub const FLAG_NO_HOST: libc::c_int = 0x040;
pub const VALIDATE_ERROR: libc::c_int = 0x001;
pub const PERM_ROOT: libc::c_int = 0x01;
pub const MODE_ERROR: libc::c_int = 0x00000200;
pub const ROOT_GID: libc::c_int = 0;
pub const SLOG_RAW_MSG: libc::c_int = 0x04;
pub const VALIDATE_SUCCESS: libc::c_int = 0x002;
pub const NOT_FOUND_DOT: libc::c_int = 2;
pub const NOT_FOUND: libc::c_int = 1;
pub const MODE_CHECK: libc::c_int = 0x00000100;
pub const PERM_RUNAS: libc::c_int = 0x05;
pub const PERM_USER: libc::c_int = 0x02;
pub const ENAMETOOLONG: libc::c_int = 36;
pub const SETDEF_CMND: libc::c_int = 0x10;
pub const SUDOERS_GID: libc::c_int = 0;
pub const PERM_SUDOERS: libc::c_int = 0x04;
pub const AI_FQDN: libc::c_int = 0x0002;
pub const PF_UNSPEC: libc::c_int = 0;
pub const EAI_MEMORY: libc::c_int = 5;
pub const RLIM_INFINITY: libc::c_int = -1;
pub const FOUND: libc::c_int = 0;

pub type __rlim_t = libc::c_ulong;
pub type rlim_t = __rlim_t;

pub type __rlimit_resource = libc::c_uint;
pub const __RLIM_NLIMITS: __rlimit_resource = 16;
pub const __RLIMIT_NLIMITS: __rlimit_resource = 16;
pub const __RLIMIT_RTTIME: __rlimit_resource = 15;
pub const __RLIMIT_RTPRIO: __rlimit_resource = 14;
pub const __RLIMIT_NICE: __rlimit_resource = 13;
pub const __RLIMIT_MSGQUEUE: __rlimit_resource = 12;
pub const __RLIMIT_SIGPENDING: __rlimit_resource = 11;
pub const __RLIMIT_LOCKS: __rlimit_resource = 10;
pub const __RLIMIT_MEMLOCK: __rlimit_resource = 8;
pub const __RLIMIT_NPROC: __rlimit_resource = 6;
pub const RLIMIT_AS: __rlimit_resource = 9;
pub const __RLIMIT_OFILE: __rlimit_resource = 7;
pub const RLIMIT_NOFILE: __rlimit_resource = 7;
pub const __RLIMIT_RSS: __rlimit_resource = 5;
pub const RLIMIT_CORE: __rlimit_resource = 4;
pub const RLIMIT_STACK: __rlimit_resource = 3;
pub const RLIMIT_DATA: __rlimit_resource = 2;
pub const RLIMIT_FSIZE: __rlimit_resource = 1;
pub const RLIMIT_CPU: __rlimit_resource = 0;
pub const ENTRY_TYPE_ANY: __rlimit_resource = 0x00;

pub type __socklen_t = libc::c_uint;
pub type socklen_t = __socklen_t;
pub type sa_family_t = libc::c_ushort;

#[derive(Copy, Clone)]
#[repr(C)]
pub struct addrinfo {
    pub ai_flags: libc::c_int,
    pub ai_family: libc::c_int,
    pub ai_socktype: libc::c_int,
    pub ai_protocol: libc::c_int,
    pub ai_addrlen: socklen_t,
    pub ai_addr: *mut sockaddr,
    pub ai_canonname: *mut libc::c_char,
    pub ai_next: *mut addrinfo,
}
#[derive(Copy, Clone)]
#[repr(C)]
pub struct sockaddr {
    pub sa_family: sa_family_t,
    pub sa_data: [libc::c_char; 14],
}
#[derive(Copy, Clone)]
#[repr(C)]
pub struct sudo_nss {
    pub entries: C2RustUnnamed_7,
    pub open: Option<unsafe extern "C" fn(*mut sudo_nss) -> libc::c_int>,
    pub close: Option<unsafe extern "C" fn(*mut sudo_nss) -> libc::c_int>,
    pub parse: Option<unsafe extern "C" fn(*mut sudo_nss) -> *mut sudoers_parse_tree>,
    pub query: Option<unsafe extern "C" fn(*mut sudo_nss, *mut passwd) -> libc::c_int>,
    pub getdefs: Option<unsafe extern "C" fn(*mut sudo_nss) -> libc::c_int>,
    pub handle: *mut libc::c_void,
    pub parse_tree: *mut sudoers_parse_tree,
    pub ret_if_found: bool,
    pub ret_if_notfound: bool,
}
#[derive(Copy, Clone)]
#[repr(C)]
pub struct C2RustUnnamed_7 {
    pub tqe_next: *mut sudo_nss,
    pub tqe_prev: *mut *mut sudo_nss,
}
#[derive(Copy, Clone)]
#[repr(C)]
pub struct sudo_nss_list {
    pub tqh_first: *mut sudo_nss,
    pub tqh_last: *mut *mut sudo_nss,
}
#[derive(Copy, Clone)]
#[repr(C)]
pub struct rlimit {
    pub rlim_cur: rlim_t,
    pub rlim_max: rlim_t,
}
pub type __rlimit_resource_t = __rlimit_resource;

#[macro_export]
macro_rules! MATCHES {
    ($s:expr, $v:expr, $num:expr) => {
        strncmp(
            ($s),
            ($v) as *const u8 as *const libc::c_char,
            (::core::mem::size_of::<[libc::c_char; $num]>() as libc::c_ulong)
                .wrapping_sub(1 as libc::c_ulong),
        ) == 0 as libc::c_int
            && *($s).offset(
                (::core::mem::size_of::<[libc::c_char; $num]>() as libc::c_ulong)
                    .wrapping_sub(1 as libc::c_ulong) as isize,
            ) as libc::c_int
                != '\0' as i32
    };
}

#[macro_export]
macro_rules! LOCALEDIR {
    () => {
        b"/usr/share/locale\0" as *const u8 as *const libc::c_char
    };
}
/*
 * Prototypes
 */
#[no_mangle]
pub static mut sudo_user: sudo_user = sudo_user {
    pw: 0 as *const passwd as *mut passwd,
    _runas_pw: 0 as *const passwd as *mut passwd,
    _runas_gr: 0 as *const group as *mut group,
    cmnd_stat: 0 as *const stat as *mut stat,
    name: 0 as *const libc::c_char as *mut libc::c_char,
    path: 0 as *const libc::c_char as *mut libc::c_char,
    tty: 0 as *const libc::c_char as *mut libc::c_char,
    ttypath: 0 as *const libc::c_char as *mut libc::c_char,
    host: 0 as *const libc::c_char as *mut libc::c_char,
    shost: 0 as *const libc::c_char as *mut libc::c_char,
    runhost: 0 as *const libc::c_char as *mut libc::c_char,
    srunhost: 0 as *const libc::c_char as *mut libc::c_char,
    prompt: 0 as *const libc::c_char as *mut libc::c_char,
    cmnd: 0 as *const libc::c_char as *mut libc::c_char,
    cmnd_args: 0 as *const libc::c_char as *mut libc::c_char,
    cmnd_base: 0 as *const libc::c_char as *mut libc::c_char,
    cmnd_safe: 0 as *const libc::c_char as *mut libc::c_char,
    class_name: 0 as *const libc::c_char as *mut libc::c_char,
    krb5_ccname: 0 as *const libc::c_char as *mut libc::c_char,
    gid_list: 0 as *const gid_list as *mut gid_list,
    env_vars: 0 as *const *mut libc::c_char,
    role: 0 as *const libc::c_char as *mut libc::c_char,
    type_0: 0 as *const libc::c_char as *mut libc::c_char,
    cwd: 0 as *const libc::c_char,
    iolog_file: 0 as *const libc::c_char as *mut libc::c_char,
    gids: 0 as *const gid_t as *mut gid_t,
    execfd: 0,
    ngids: 0,
    closefrom: 0,
    lines: 0,
    cols: 0,
    flags: 0,
    max_groups: 0,
    timeout: 0,
    umask: 0,
    uid: 0,
    gid: 0,
    sid: 0,
};
#[no_mangle]
pub static mut list_pw: *mut passwd = 0 as *const passwd as *mut passwd;
static mut prev_user: *mut libc::c_char = 0 as *const libc::c_char as *mut libc::c_char;
static mut runas_user: *mut libc::c_char = 0 as *const libc::c_char as *mut libc::c_char;
static mut runas_group: *mut libc::c_char = 0 as *const libc::c_char as *mut libc::c_char;
static mut snl: *mut sudo_nss_list = 0 as *const sudo_nss_list as *mut sudo_nss_list;
static mut unknown_runas_uid: bool = false;
static mut unknown_runas_gid: bool = false;
static mut nproclimit: rlimit = rlimit {
    rlim_cur: 0,
    rlim_max: 0,
};

/* XXX - must be extern for audit bits of sudo_auth.c */
#[no_mangle]
pub static mut NewArgc: libc::c_int = 0;
#[no_mangle]
pub static mut NewArgv: *mut *mut libc::c_char =
    0 as *const *mut libc::c_char as *mut *mut libc::c_char;

/*
 * Unlimit the number of processes since Linux's setuid() will
 * apply resource limits when changing uid and return EAGAIN if
 * nproc would be exceeded by the uid switch.
 */
fn unlimit_nproc() {
    let mut rl: rlimit = rlimit {
        rlim_cur: 0,
        rlim_max: 0,
    };
    unsafe {
        debug_decl!(SUDOERS_DEBUG_UTIL!());

        if getrlimit(__RLIMIT_NPROC, &mut nproclimit) != 0 as libc::c_int {
            sudo_warn!(b"getrlimit\0" as *const u8 as *const libc::c_char,);
        }
        rl.rlim_max = RLIM_INFINITY as __rlim_t;
        rl.rlim_cur = rl.rlim_max;
        if setrlimit(__RLIMIT_NPROC, &rl) != 0 as libc::c_int {
            rl.rlim_max = nproclimit.rlim_max;
            rl.rlim_cur = rl.rlim_max;
            if setrlimit(__RLIMIT_NPROC, &rl) != 0 as libc::c_int {
                sudo_warn!(b"setrlimit\0" as *const u8 as *const libc::c_char,);
            }
        }
        debug_return!();
    } //unsafe
}

/*
 * Restore saved value of RLIMIT_NPROC.
 */
fn restore_nproc() {
    unsafe {
        debug_decl!(SUDOERS_DEBUG_UTIL!());

        if setrlimit(__RLIMIT_NPROC, &nproclimit) != 0 as libc::c_int {
            sudo_warn!(b"setrlimit\0" as *const u8 as *const libc::c_char,);
        }

        debug_return!();
    } //unsafe
}

#[no_mangle]
pub fn sudoers_policy_init(
    mut info: *mut libc::c_void,
    mut envp: *const *mut libc::c_char,
) -> libc::c_int {
    let mut nss: *mut sudo_nss = std::ptr::null_mut::<sudo_nss>();
    let mut nss_next: *mut sudo_nss = std::ptr::null_mut::<sudo_nss>();
    let mut oldlocale: libc::c_int = 0;
    let mut sources: libc::c_int = 0 as libc::c_int;
    let mut ret: libc::c_int = -(1 as libc::c_int);
    unsafe {
        debug_decl!(SUDOERS_DEBUG_PLUGIN!());

        bindtextdomain(
            b"sudoers\0" as *const u8 as *const libc::c_char,
            LOCALEDIR!(),
        );

        /* Register fatal/fatalx callback. */
        sudo_fatal_callback_register_v1(Some(sudoers_cleanup as unsafe extern "C" fn() -> ()));

        /* Initialize environment functions (including replacements). */
        if !env_init(envp) {
            debug_return_int!(-(1 as libc::c_int));
        }

        /* Setup defaults data structures. */
        if !init_defaults() {
            sudo_warnx!(
                b"unable to initialize sudoers default values\0" as *const u8
                    as *const libc::c_char,
            );
            debug_return_int!(-(1 as libc::c_int));
        }

        /* Parse info from front-end. */
        sudo_mode = sudoers_policy_deserialize_info(info, &mut runas_user, &mut runas_group);
        if ISSET!(sudo_mode, MODE_ERROR) != 0 {
            debug_return_int!(-(1 as libc::c_int));
        }

        if !init_vars(envp) {
            debug_return_int!(-(1 as libc::c_int));
        }

        /* Parse nsswitch.conf for sudoers order. */
        snl = sudo_read_nss();

        /* LDAP or NSS may modify the euid so we need to be root for the open. */
        if !set_perms(PERM_ROOT) {
            debug_return_int!(-(1 as libc::c_int));
        }

        /*
         * Open and parse sudoers, set global defaults.
         * Uses the C locale unless another is specified in sudoers.
         */
        sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &mut oldlocale);
        sudo_warn_set_locale_func_v1(Some(
            sudoers_warn_setlocale as unsafe extern "C" fn(bool, *mut libc::c_int) -> bool,
        ));
        init_parser(sudoers_file, false);
        nss = (*snl).tqh_first;
        while !nss.is_null() && {
            nss_next = (*nss).entries.tqe_next;
            1 as libc::c_int != 0
        } {
            if ((*nss).open).expect("non-null function pointer")(nss) == -(1 as libc::c_int) || {
                (*nss).parse_tree = ((*nss).parse).expect("non-null function pointer")(nss);
                ((*nss).parse_tree).is_null()
            } {
                if !((*nss).entries.tqe_next).is_null() {
                    (*(*nss).entries.tqe_next).entries.tqe_prev = (*nss).entries.tqe_prev;
                } else {
                    (*snl).tqh_last = (*nss).entries.tqe_prev;
                }
                *(*nss).entries.tqe_prev = (*nss).entries.tqe_next;
            } else {
                sources += 1;
                if ((*nss).getdefs).expect("non-null function pointer")(nss) == -(1 as libc::c_int)
                    || !update_defaults(
                        (*nss).parse_tree,
                        std::ptr::null_mut::<defaults_list>(),
                        SETDEF_GENERIC | SETDEF_HOST | SETDEF_USER | SETDEF_RUNAS,
                        false,
                    )
                {
                    log_warningx(
                        SLOG_SEND_MAIL | SLOG_NO_STDERR,
                        b"problem with defaults entries\0" as *const u8 as *const libc::c_char,
                    );
                }
            }
            nss = nss_next;
        }
        'cleanup: loop {
            if sources == 0 as libc::c_int {
                sudo_warnx!(
                    b"no valid sudoers sources found, quitting\0" as *const u8
                        as *const libc::c_char,
                );
                break 'cleanup;
            }

            /* Set login class if applicable (after sudoers is parsed). */
            if set_loginclass(if !(sudo_user._runas_pw).is_null() {
                sudo_user._runas_pw
            } else {
                sudo_user.pw
            }) {
                ret = true as libc::c_int;
            }

            if def_match_group_by_gid!() == 0 || !def_legacy_group_processing!() == 0 {
                def_match_group_by_gid!() = false as libc::c_int;
                def_legacy_group_processing!() = false as libc::c_int;
            }

            /*
             * Emulate cmnd_no_wait option by disabling PAM session, PTY allocation
             * and I/O logging. This will cause sudo to execute the given command
             * directly instead of forking a separate process for it.
             */
            if def_cmnd_no_wait!() != 0 {
                def_pam_setcred!() = false as libc::c_int;
                def_pam_session!() = false as libc::c_int;
                def_use_pty!() = false as libc::c_int;
                def_log_input!() = false as libc::c_int;
                def_log_output!() = false as libc::c_int;
            }
            break;
        }

        //cleanup:
        if !restore_perms() {
            ret = -(1 as libc::c_int);
        }

        /* Restore user's locale. */
        sudo_warn_set_locale_func_v1(None);
        sudoers_setlocale(oldlocale, std::ptr::null_mut::<libc::c_int>());

        debug_return_int!(ret);
    } //unsafe
}

#[no_mangle]
pub fn sudoers_policy_main(
    mut argc: libc::c_int,
    mut argv: *const *mut libc::c_char,
    mut pwflag: libc::c_int,
    mut env_add: *mut *mut libc::c_char,
    mut verbose: bool,
    mut closure: *mut libc::c_void,
) -> libc::c_int {
    let mut edit_argv: *mut *mut libc::c_char = std::ptr::null_mut::<*mut libc::c_char>();
    let mut iolog_path: *mut libc::c_char = std::ptr::null_mut::<libc::c_char>();
    let mut cmnd_umask: mode_t = ACCESSPERMS!() as mode_t;
    let mut nss: *mut sudo_nss = std::ptr::null_mut::<sudo_nss>();
    let mut cmnd_status: libc::c_int = -(1 as libc::c_int);
    let mut oldlocale: libc::c_int = 0;
    let mut validated: libc::c_int = 0;
    let mut ret: libc::c_int = -(1 as libc::c_int);
    unsafe {
        debug_decl!(SUDOERS_DEBUG_PLUGIN!());

        sudo_warn_set_locale_func_v1(Some(
            sudoers_warn_setlocale as unsafe extern "C" fn(bool, *mut libc::c_int) -> bool,
        ));

        unlimit_nproc();

        'done: loop {
            'bad: loop {
                /* Is root even allowed to run sudo? */
                if sudo_user.uid == 0 as libc::c_uint && def_root_sudo!() == 0 {
                    /* Not an audit event. */
                    sudo_warnx!(
                        b"sudoers specifies that root is not allowed to sudo\0" as *const u8
                            as *const libc::c_char,
                    );
                    break 'bad;
                }

                if !set_perms(PERM_INITIAL) {
                    break 'bad;
                }

                /* Environment variables specified on the command line. */
                if !env_add.is_null() && !(*env_add.offset(0 as libc::c_int as isize)).is_null() {
                    sudo_user.env_vars = env_add as *const *mut libc::c_char;
                }

                /*
                 * Make a local copy of argc/argv, with special handling
                 * for pseudo-commands and the '-i' option.
                 */
                if argc == 0 as libc::c_int {
                    NewArgc = 1 as libc::c_int;
                    NewArgv = reallocarray(
                        std::ptr::null_mut::<libc::c_void>(),
                        (NewArgc + 1 as libc::c_int) as size_t,
                        ::core::mem::size_of::<*mut libc::c_char>() as libc::c_ulong,
                    ) as *mut *mut libc::c_char;
                    if NewArgv.is_null() {
                        sudo_warnx!(
                            b"%s: %s\0" as *const u8 as *const libc::c_char,
                            get_function_name!(),
                            b"unable to allocate memory\0" as *const u8 as *const libc::c_char
                        );
                        break 'done;
                    }
                    let fresh0 = &mut *NewArgv.offset(0 as libc::c_int as isize);
                    *fresh0 = sudo_user.cmnd;
                    let fresh1 = &mut *NewArgv.offset(1 as libc::c_int as isize);
                    *fresh1 = std::ptr::null_mut::<libc::c_char>();
                } else {
                    /* Must leave an extra slot before NewArgv for bash's --login */
                    NewArgc = argc;
                    NewArgv = reallocarray(
                        std::ptr::null_mut::<libc::c_void>(),
                        (NewArgc + 2 as libc::c_int) as size_t,
                        ::core::mem::size_of::<*mut libc::c_char>() as libc::c_ulong,
                    ) as *mut *mut libc::c_char;
                    if NewArgv.is_null() {
                        sudo_warnx!(
                            b"%s: %s\0" as *const u8 as *const libc::c_char,
                            get_function_name!(),
                            b"unable to allocate memory\0" as *const u8 as *const libc::c_char
                        );
                        break 'done;
                    }
                    NewArgv = NewArgv.offset(1); /* reserve an extra slot for --login */
                    memcpy(
                        NewArgv as *mut libc::c_void,
                        argv as *const libc::c_void,
                        (argc as libc::c_ulong).wrapping_mul(
                            ::core::mem::size_of::<*mut libc::c_char>() as libc::c_ulong,
                        ),
                    );
                    let fresh2 = &mut *NewArgv.offset(NewArgc as isize);
                    *fresh2 = std::ptr::null_mut::<libc::c_char>();
                    if ISSET!(sudo_mode, MODE_LOGIN_SHELL) != 0 && !(sudo_user._runas_pw).is_null()
                    {
                        let fresh3 = &mut *NewArgv.offset(0 as libc::c_int as isize);
                        *fresh3 = strdup((*sudo_user._runas_pw).pw_shell);
                        if (*NewArgv.offset(0 as libc::c_int as isize)).is_null() {
                            sudo_warnx!(
                                b"%s: %s\0" as *const u8 as *const libc::c_char,
                                get_function_name!(),
                                b"unable to allocate memory\0" as *const u8 as *const libc::c_char
                            );
                            free(NewArgv as *mut libc::c_void);
                            break 'done;
                        }
                    }
                }

                /* If given the -P option, set the "preserve_groups" flag. */
                if ISSET!(sudo_mode, MODE_PRESERVE_GROUPS) != 0 {
                    def_preserve_groups!() = true as libc::c_int;
                }

                /* Find command in path and apply per-command Defaults. */
                cmnd_status = set_cmnd();
                if cmnd_status == NOT_FOUND_ERROR {
                    break 'done;
                }

                /* Check for -C overriding def_closefrom. */
                if user_closefrom!() >= 0 && user_closefrom!() != def_closefrom!() {
                    if def_closefrom_override!() == 0 {
                        /* XXX - audit? */
                        sudo_warnx!(
                            b"you are not permitted to use the -C option\0" as *const u8
                                as *const libc::c_char,
                        );
                        break 'bad;
                    }
                    def_closefrom!() = user_closefrom!();
                }

                /*
                 * Check sudoers sources, using the locale specified in sudoers.
                 */
                sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &mut oldlocale);
                validated = sudoers_lookup(snl, sudo_user.pw, FLAG_NO_USER | FLAG_NO_HOST, pwflag);
                if ISSET!(validated, VALIDATE_ERROR) != 0 {
                    /* The lookup function should have printed an error. */
                    break 'done;
                }

                /* Restore user's locale. */
                sudoers_setlocale(oldlocale, std::ptr::null_mut::<libc::c_int>());

                if (sudo_user.cmnd_safe).is_null() {
                    sudo_user.cmnd_safe = strdup(sudo_user.cmnd);
                    if (sudo_user.cmnd_safe).is_null() {
                        sudo_warnx!(
                            b"%s: %s\0" as *const u8 as *const libc::c_char,
                            get_function_name!(),
                            b"unable to allocate memory\0" as *const u8 as *const libc::c_char
                        );
                        break 'done;
                    }
                }

                /* Defer uid/gid checks until after defaults have been updated. */
                if unknown_runas_uid as libc::c_int != 0 && def_runas_allow_unknown_id!() == 0 {
                    audit_failure(
                        NewArgc,
                        NewArgv,
                        b"unknown user: %s\0" as *const u8 as *const libc::c_char,
                        (*sudo_user._runas_pw).pw_name,
                    );
                    sudo_warnx!(
                        b"unknown user: %s\0" as *const u8 as *const libc::c_char,
                        (*sudo_user._runas_pw).pw_name
                    );
                    break 'done;
                }

                if !(sudo_user._runas_gr).is_null()
                    && unknown_runas_gid as libc::c_int != 0
                    && def_runas_allow_unknown_id!() == 0
                {
                    audit_failure(
                        NewArgc,
                        NewArgv,
                        b"unknown group: %s\0" as *const u8 as *const libc::c_char,
                        (*sudo_user._runas_gr).gr_name,
                    );
                    sudo_warnx!(
                        b"unknown group: %s\0" as *const u8 as *const libc::c_char,
                        (*sudo_user._runas_gr).gr_name
                    );
                    break 'done;
                }

                /*if !(sudo_user._runas_gr).is_null() {
                    if unknown_runas_gid as libc::c_int != 0 && def_runas_allow_unknown_id!() == 0 {
                        audit_failure(
                            NewArgc,
                            NewArgv,
                            b"unknown group: %s\0" as *const u8 as *const libc::c_char,
                            (*sudo_user._runas_gr).gr_name,
                        );
                        sudo_warnx!(
                            b"unknown group: %s\0" as *const u8 as *const libc::c_char,
                            (*sudo_user._runas_gr).gr_name
                        );
                        break 'done;
                    }
                }*/

                /*
                 * Look up the timestamp dir owner if one is specified.
                 */
                if !(def_timestampowner!()).is_null() {
                    let mut pw: *mut passwd = std::ptr::null_mut::<passwd>();

                    if *(def_timestampowner!()) as libc::c_int == '#' as i32 {
                        let mut errstr: *const libc::c_char = std::ptr::null::<libc::c_char>();
                        let mut uid: uid_t = sudo_strtoid_v2(
                            (def_timestampowner!()).offset(1 as libc::c_int as isize),
                            &mut errstr,
                        );
                        if errstr.is_null() {
                            pw = sudo_getpwuid(uid);
                        }
                    }
                    if pw.is_null() {
                        pw = sudo_getpwnam(def_timestampowner!());
                    }
                    if !pw.is_null() {
                        timestamp_uid = (*pw).pw_uid;
                        timestamp_gid = (*pw).pw_gid;
                        sudo_pw_delref(pw);
                    } else {
                        log_warningx(
                            SLOG_SEND_MAIL,
                            b"timestamp owner (%s): No such user\0" as *const u8
                                as *const libc::c_char,
                            def_timestampowner!(),
                        );
                        timestamp_uid = ROOT_UID as uid_t;
                        timestamp_gid = ROOT_GID as gid_t;
                    }
                }

                /* If no command line args and "shell_noargs" is not set, error out. */
                if ISSET!(sudo_mode, MODE_IMPLIED_SHELL) != 0 && def_shell_noargs!() == 0 {
                    /* Not an audit event. */
                    ret = -(2 as libc::c_int); /* usage error */
                    break 'done;
                }

                /* Bail if a tty is required and we don't have one.  */
                if def_requiretty!() != 0 && !tty_present() {
                    audit_failure(
                        NewArgc,
                        NewArgv,
                        b"no tty\0" as *const u8 as *const libc::c_char,
                    );
                    sudo_warnx!(
                        b"sorry, you must have a tty to run sudo\0" as *const u8
                            as *const libc::c_char,
                    );
                    break 'bad;
                }

                /* Check runas user's shell. */
                if !check_user_shell(sudo_user._runas_pw) {
                    log_warningx(
                        SLOG_RAW_MSG,
                        b"invalid shell for user %s: %s\0" as *const u8 as *const libc::c_char,
                        (*sudo_user._runas_pw).pw_name,
                        (*sudo_user._runas_pw).pw_shell,
                    );
                    break 'bad;
                }

                /*
                 * We don't reset the environment for sudoedit or if the user
                 * specified the -E command line flag and they have setenv privs.
                 */
                if ISSET!(sudo_mode, MODE_EDIT) != 0
                    || (ISSET!(sudo_mode, MODE_PRESERVE_ENV) != 0 && def_setenv!() != 0)
                {
                    def_env_reset!() = false as libc::c_int;
                }

                /* Build a new environment that avoids any nasty bits. */
                if !rebuild_env() {
                    break 'bad;
                }

                /* Require a password if sudoers says so.  */
                match check_user(validated, sudo_mode) {
                    1 => { /* user authenticated successfully. */ }
                    0 => {
                        /* Note: log_denial() calls audit for us. */
                        if ISSET!(validated, VALIDATE_SUCCESS) != 0 {
                            /* Only display a denial message if no password was read. */
                            if !log_denial(validated, def_passwd_tries!() <= 0) {
                                break 'done;
                            }
                        }
                        break 'bad;
                    }
                    _ => {
                        /* some other error, ret is -1. */
                        break 'done;
                    }
                }

                /* If run as root with SUDO_USER set, set sudo_user.pw to that user. */
                /* XXX - causes confusion when root is not listed in sudoers */

                if ISSET!(sudo_mode, MODE_RUN | MODE_EDIT) != 0
                    && !prev_user.is_null()
                    && sudo_user.uid == 0 as libc::c_int as libc::c_uint
                    && strcmp(prev_user, b"root\0" as *const u8 as *const libc::c_char)
                        != 0 as libc::c_int
                {
                    let mut pw_0: *mut passwd = std::ptr::null_mut::<passwd>();

                    pw_0 = sudo_getpwnam(prev_user);
                    if !pw_0.is_null() {
                        if !(sudo_user.pw).is_null() {
                            sudo_pw_delref(sudo_user.pw);
                        }
                        sudo_user.pw = pw_0;
                    }
                }

                /*if ISSET!(sudo_mode, MODE_RUN | MODE_EDIT) != 0 && !prev_user.is_null() {
                    if sudo_user.uid == 0 as libc::c_int as libc::c_uint
                        && strcmp(prev_user, b"root\0" as *const u8 as *const libc::c_char)
                            != 0 as libc::c_int
                    {
                        let mut pw_0: *mut passwd = std::ptr::null_mut::<passwd>();

                        pw_0 = sudo_getpwnam(prev_user);
                        if !pw_0.is_null() {
                            if !(sudo_user.pw).is_null() {
                                sudo_pw_delref(sudo_user.pw);
                            }
                            sudo_user.pw = pw_0;
                        }
                    }
                }*/

                /* If the user was not allowed to run the command we are done. */
                if ISSET!(validated, VALIDATE_SUCCESS) == 0 {
                    /* Note: log_failure() calls audit for us. */
                    if !log_failure(validated, cmnd_status) {
                        break 'done;
                    }
                    break 'bad;
                }

                /* Create Ubuntu-style dot file to indicate sudo was successful. */
                if create_admin_success_flag() == -(1 as libc::c_int) {
                    break 'done;
                }

                /* Finally tell the user if the command did not exist. */
                if cmnd_status == NOT_FOUND_DOT {
                    audit_failure(
                        NewArgc,
                        NewArgv,
                        b"command in current directory\0" as *const u8 as *const libc::c_char,
                    );
                    sudo_warnx!(
                b"ignoring \"%s\" found in '.'\nUse \"sudo ./%s\" if this is the \"%s\" you wish to run.\0" as *const u8 as *const libc::c_char,
                sudo_user.cmnd,
                sudo_user.cmnd,
                sudo_user.cmnd
            );
                    break 'bad;
                } else if cmnd_status == NOT_FOUND {
                    if ISSET!(sudo_mode, MODE_CHECK) != 0 {
                        audit_failure(
                            NewArgc,
                            NewArgv,
                            b"%s: command not found\0" as *const u8 as *const libc::c_char,
                            *NewArgv.offset(0 as libc::c_int as isize),
                        );
                    } else {
                        audit_failure(
                            NewArgc,
                            NewArgv,
                            b"%s: command not found\0" as *const u8 as *const libc::c_char,
                            sudo_user.cmnd,
                        );
                        sudo_warnx!(
                            b"%s: command not found\0" as *const u8 as *const libc::c_char,
                            sudo_user.cmnd
                        );
                    }
                    break 'bad;
                }

                /* If user specified a timeout make sure sudoers allows it. */
                if def_user_command_timeouts!() == 0 && sudo_user.timeout > 0 {
                    /* XXX - audit/log? */
                    sudo_warnx!(
                        b"sorry, you are not allowed set a command timeout\0" as *const u8
                            as *const libc::c_char,
                    );
                    break 'bad;
                }

                /* If user specified env vars make sure sudoers allows it. */
                if ISSET!(sudo_mode, MODE_RUN) != 0 && def_setenv!() == 0 {
                    if ISSET!(sudo_mode, MODE_PRESERVE_ENV) != 0 {
                        /* XXX - audit/log? */
                        sudo_warnx!(
                            b"sorry, you are not allowed to preserve the environment\0" as *const u8
                                as *const libc::c_char,
                        );
                        break 'bad;
                    } else if !validate_env_vars(sudo_user.env_vars) {
                        break 'bad;
                    }

                    /*} else {
                        if !validate_env_vars(sudo_user.env_vars) {
                            break 'bad;
                        }
                    }*/
                }

                if ISSET!(sudo_mode, (MODE_RUN | MODE_EDIT)) != 0
                    && (def_log_input!() != 0 || def_log_output!() != 0)
                    && !(def_iolog_file!()).is_null()
                    && !(def_iolog_dir!()).is_null()
                {
                    let prefix: [libc::c_char; 12] =
                        *::core::mem::transmute::<&[u8; 12], &[libc::c_char; 12]>(b"iolog_path=\0");
                    iolog_path = expand_iolog_path(
                        prefix.as_ptr(),
                        def_iolog_dir!(),
                        def_iolog_file!(),
                        &mut sudo_user.iolog_file,
                    );
                    if iolog_path.is_null() {
                        if def_ignore_iolog_errors!() == 0 {
                            break 'done;
                        }
                        /* Unable to expand I/O log path, disable I/O logging. */
                        def_log_input!() = false as libc::c_int;
                        def_log_output!() = false as libc::c_int;
                    } else {
                        sudo_user.iolog_file = (sudo_user.iolog_file).offset(1);
                    }
                }

                /*if ISSET!(sudo_mode, (MODE_RUN | MODE_EDIT)) != 0 {
                    if (def_log_input!() != 0 || def_log_output!() != 0)
                        && !(def_iolog_file!()).is_null()
                        && !(def_iolog_dir!()).is_null()
                    {
                        let prefix: [libc::c_char; 12] =
                            *::core::mem::transmute::<&[u8; 12], &[libc::c_char; 12]>(
                                b"iolog_path=\0",
                            );
                        iolog_path = expand_iolog_path(
                            prefix.as_ptr(),
                            def_iolog_dir!(),
                            def_iolog_file!(),
                            &mut sudo_user.iolog_file,
                        );
                        if iolog_path.is_null() {
                            if def_ignore_iolog_errors!() == 0 {
                                break 'done;
                            }
                            /* Unable to expand I/O log path, disable I/O logging. */
                            def_log_input!() = false as libc::c_int;
                            def_log_output!() = false as libc::c_int;
                        } else {
                            sudo_user.iolog_file = (sudo_user.iolog_file).offset(1);
                        }
                    }
                }*/

                if !log_allowed(validated) && def_ignore_logfile_errors!() == 0 {
                    break 'bad;
                }

                match sudo_mode & MODE_MASK {
                    MODE_CHECK => {
                        ret = display_cmnd(
                            snl,
                            if !list_pw.is_null() {
                                list_pw
                            } else {
                                sudo_user.pw
                            },
                        );
                    }
                    MODE_LIST => {
                        ret = display_privs(
                            snl,
                            if !list_pw.is_null() {
                                list_pw
                            } else {
                                sudo_user.pw
                            },
                            verbose,
                        );
                    }
                    MODE_VALIDATE => {
                        /* Nothing to do. */
                        ret = true as libc::c_int;
                    }
                    MODE_RUN | MODE_EDIT => { /* ret set by sudoers_policy_exec_setup() below. */ }
                    _ => {
                        /* Should not happen. */
                        sudo_warnx!(
                            b"internal error, unexpected sudo mode 0x%x\0" as *const u8
                                as *const libc::c_char,
                            sudo_mode
                        );
                        break 'done;
                    }
                }

                /* Cleanup sudoers sources */
                nss = (*snl).tqh_first;
                while !nss.is_null() {
                    ((*nss).close).expect("non-null function pointer")(nss);
                    nss = (*nss).entries.tqe_next;
                }
                if !(def_group_plugin!()).is_null() {
                    group_plugin_unload();
                }
                init_parser(std::ptr::null::<libc::c_char>(), false);

                if ISSET!(sudo_mode, (MODE_VALIDATE | MODE_CHECK | MODE_LIST)) != 0 {
                    /* ret already set appropriately */
                    break 'done;
                }

                /*
                 * Set umask based on sudoers.
                 * If user's umask is more restrictive, OR in those bits too
                 * unless umask_override is set.
                 */
                if def_umask!() != ACCESSPERMS!() as libc::c_uint {
                    cmnd_umask = def_umask!();
                    if def_umask_override!() == 0 {
                        cmnd_umask |= user_umask!();
                    }
                }

                if ISSET!(sudo_mode, MODE_LOGIN_SHELL) != 0 {
                    let mut p: *mut libc::c_char = std::ptr::null_mut::<libc::c_char>();

                    /* Convert /bin/sh -> -sh so shell knows it is a login shell */
                    p = strrchr(*NewArgv.offset(0 as libc::c_int as isize), '/' as i32);
                    if p.is_null() {
                        p = *NewArgv.offset(0 as libc::c_int as isize);
                    }
                    *p = '-' as i32 as libc::c_char;
                    let fresh4 = &mut *NewArgv.offset(0 as libc::c_int as isize);
                    *fresh4 = p;

                    /*
                     * Newer versions of bash require the --login option to be used
                     * in conjunction with the -c option even if the shell name starts
                     * with a '-'.  Unfortunately, bash 1.x uses -login, not --login
                     * so this will cause an error for that.
                     */
                    if NewArgc > 1 as libc::c_int
                        && strcmp(
                            *NewArgv.offset(0 as libc::c_int as isize),
                            b"-bash\0" as *const u8 as *const libc::c_char,
                        ) == 0 as libc::c_int
                        && strcmp(
                            *NewArgv.offset(1 as libc::c_int as isize),
                            b"-c\0" as *const u8 as *const libc::c_char,
                        ) == 0 as libc::c_int
                    {
                        /* Use the extra slot before NewArgv so we can store --login. */
                        NewArgv = NewArgv.offset(-1);
                        NewArgc += 1;
                        let fresh5 = &mut *NewArgv.offset(0 as libc::c_int as isize);
                        *fresh5 = *NewArgv.offset(1 as libc::c_int as isize);
                        let fresh6 = &mut *NewArgv.offset(1 as libc::c_int as isize);
                        *fresh6 =
                            b"--login\0" as *const u8 as *const libc::c_char as *mut libc::c_char;
                    }
                }

                /* Insert system-wide environment variables. */

                if !(def_restricted_env_file!()).is_null()
                    && !read_env_file(def_restricted_env_file!(), false, true)
                {
                    sudo_warn!(
                        b"%s\0" as *const u8 as *const libc::c_char,
                        def_restricted_env_file!()
                    );
                }

                /*if !(def_restricted_env_file!()).is_null() {
                    if !read_env_file(def_restricted_env_file!(), false, true) {
                        sudo_warn!(
                            b"%s\0" as *const u8 as *const libc::c_char,
                            def_restricted_env_file!()
                        );
                    }
                }*/
                /*if !(def_env_file!()).is_null() {
                    if !read_env_file(def_env_file!(), false, false) {
                        sudo_warn!(b"%s\0" as *const u8 as *const libc::c_char, def_env_file!());
                    }
                }*/
                if !(def_env_file!()).is_null() && !read_env_file(def_env_file!(), false, false) {
                    sudo_warn!(b"%s\0" as *const u8 as *const libc::c_char, def_env_file!());
                }

                /* Insert user-specified environment variables. */
                if !insert_env_vars(sudo_user.env_vars) {
                    break 'done;
                }

                /* Note: must call audit before uid change. */
                if ISSET!(sudo_mode, MODE_EDIT) != 0 {
                    let mut edit_argc: libc::c_int = 0;
                    let mut env_editor: *const libc::c_char = std::ptr::null::<libc::c_char>();

                    free(sudo_user.cmnd_safe as *mut libc::c_void);
                    sudo_user.cmnd_safe = find_editor(
                        NewArgc - 1 as libc::c_int,
                        NewArgv.offset(1 as libc::c_int as isize),
                        &mut edit_argc,
                        &mut edit_argv,
                        std::ptr::null::<*mut libc::c_char>(),
                        &mut env_editor,
                        false,
                    );
                    if (sudo_user.cmnd_safe).is_null() {
                        if *__errno_location() != ENOENT {
                            break 'done;
                        }
                        audit_failure(
                            NewArgc,
                            NewArgv,
                            b"%s: command not found\0" as *const u8 as *const libc::c_char,
                            if !env_editor.is_null() {
                                env_editor
                            } else {
                                def_editor!()
                            },
                        );
                        sudo_warnx!(
                            b"%s: command not found\0" as *const u8 as *const libc::c_char,
                            if !env_editor.is_null() {
                                env_editor
                            } else {
                                def_editor!()
                            },
                        );
                        break 'bad;
                    }
                    if audit_success(edit_argc, edit_argv) != 0 as libc::c_int
                        && def_ignore_audit_errors!() == 0
                    {
                        break 'done;
                    }

                    /* We want to run the editor with the unmodified environment. */
                    env_swap_old();
                } else if audit_success(NewArgc, NewArgv) != 0 as libc::c_int
                    && def_ignore_audit_errors!() == 0
                {
                    break 'done;
                }

                /*} else {
                    if audit_success(NewArgc, NewArgv) != 0 as libc::c_int
                        && def_ignore_audit_errors!() == 0
                    {
                        break 'done;
                    }
                }*/

                /* Setup execution environment to pass back to front-end. */
                ret = sudoers_policy_exec_setup(
                    if !edit_argv.is_null() {
                        edit_argv
                    } else {
                        NewArgv
                    },
                    env_get(),
                    cmnd_umask,
                    iolog_path,
                    closure,
                );

                /* Zero out stashed copy of environment, it is owned by the front-end. */
                env_init(std::ptr::null::<*mut libc::c_char>());

                break 'done;
            }

            //bad:
            ret = false as libc::c_int;

            break;
        }
        //done:
        if !rewind_perms() {
            ret = -(1 as libc::c_int);
        }

        restore_nproc();

        /* Destroy the password and group caches and free the contents. */
        sudo_freepwcache();
        sudo_freegrcache();

        sudo_warn_set_locale_func_v1(None);

        debug_return_int!(ret);
    } //unsafe
}

/*
 * Initialize timezone and fill in sudo_user struct.
 */
fn init_vars(mut envp: *const *mut libc::c_char) -> bool {
    let mut ep: *const *mut libc::c_char = std::ptr::null::<*mut libc::c_char>();
    let mut unknown_user: bool = false;
    unsafe {
        debug_decl!(SUDOERS_DEBUG_PLUGIN!());

        if !sudoers_initlocale(
            setlocale(LC_ALL, std::ptr::null::<libc::c_char>()),
            def_sudoers_locale!(),
        ) {
            sudo_warnx!(
                b"%s: %s\0" as *const u8 as *const libc::c_char,
                get_function_name!(),
                b"unable to allocate memory\0" as *const u8 as *const libc::c_char
            );
            debug_return_bool!(false);
        }

        ep = envp;
        while !(*ep).is_null() {
            match **ep as u8 as char {
                'K' => {
                    if MATCHES!(*ep, b"KRB5CCNAME=\0", 12) {
                        sudo_user.krb5_ccname = (*ep)
                            .offset(
                                ::core::mem::size_of::<[libc::c_char; 12]>() as libc::c_ulong
                                    as isize,
                            )
                            .offset(-(1 as libc::c_int as isize));
                    }
                }
                'P' => {
                    if MATCHES!(*ep, b"PATH=\0", 6) {
                        sudo_user.path = (*ep)
                            .offset(::core::mem::size_of::<[libc::c_char; 6]>() as libc::c_ulong
                                as isize)
                            .offset(-(1 as libc::c_int as isize));
                    }
                }
                'S' => {
                    if MATCHES!(*ep, b"SUDO_PROMPT=\0", 13) {
                        /* Don't override "sudo -p prompt" */
                        if (sudo_user.prompt).is_null() {
                            sudo_user.prompt = (*ep)
                                .offset(::core::mem::size_of::<[libc::c_char; 13]>()
                                    as libc::c_ulong
                                    as isize)
                                .offset(-(1 as libc::c_int as isize));
                        }
                    }
                    if MATCHES!(*ep, b"SUDO_USER=\0", 11) {
                        prev_user = (*ep)
                            .offset(
                                ::core::mem::size_of::<[libc::c_char; 11]>() as libc::c_ulong
                                    as isize,
                            )
                            .offset(-(1 as libc::c_int as isize));
                    }
                }
                _ => {}
            }
            ep = ep.offset(1);
        }

        /*
         * Get a local copy of the user's passwd struct and group list if we
         * don't already have them.
         */
        if (sudo_user.pw).is_null() {
            sudo_user.pw = sudo_getpwnam(sudo_user.name);
            if (sudo_user.pw).is_null() {
                /*
                 * It is not unusual for users to place "sudo -k" in a .logout
                 * file which can cause sudo to be run during reboot after the
                 * YP/NIS/NIS+/LDAP/etc daemon has died.
                 */
                if sudo_mode == MODE_KILL || sudo_mode == MODE_INVALIDATE {
                    sudo_warnx!(
                        b"unknown uid: %u\0" as *const u8 as *const libc::c_char,
                        sudo_user.uid
                    );
                    debug_return_bool!(false);
                }

                /* Need to make a fake struct passwd for the call to log_warningx(). */
                sudo_user.pw = sudo_mkpwent(
                    sudo_user.name,
                    sudo_user.uid,
                    sudo_user.gid,
                    std::ptr::null::<libc::c_char>(),
                    std::ptr::null::<libc::c_char>(),
                );
                unknown_user = true;
            }
        }
        if (sudo_user.gid_list).is_null() {
            sudo_user.gid_list = sudo_get_gidlist(sudo_user.pw, ENTRY_TYPE_ANY as libc::c_uint);
        }

        /* Store initialize permissions so we can restore them later. */
        if !set_perms(PERM_INITIAL) {
            debug_return_bool!(false);
        }
        /* Set fqdn callback. */
        let fresh7 = &mut (*sudo_defs_table.as_mut_ptr().offset(I_FQDN)).callback;
        *fresh7 = Some(cb_fqdn as unsafe extern "C" fn(*const sudo_defs_val) -> bool);

        /* Set group_plugin callback. */
        let fresh8 = &mut (*sudo_defs_table.as_mut_ptr().offset(I_GROUP_PLUGIN)).callback;
        *fresh8 = Some(cb_group_plugin as unsafe extern "C" fn(*const sudo_defs_val) -> bool);

        /* Set runas callback. */
        let fresh9 = &mut (*sudo_defs_table.as_mut_ptr().offset(I_RUNAS_DEFAULT)).callback;
        *fresh9 = Some(cb_runas_default as unsafe extern "C" fn(*const sudo_defs_val) -> bool);

        /* Set locale callback. */
        let fresh10 = &mut (*sudo_defs_table.as_mut_ptr().offset(I_SUDOERS_LOCALE)).callback;
        *fresh10 =
            Some(sudoers_locale_callback as unsafe extern "C" fn(*const sudo_defs_val) -> bool);

        /* Set maxseq callback. */
        let fresh11 = &mut (*sudo_defs_table.as_mut_ptr().offset(I_MAXSEQ)).callback;
        *fresh11 = Some(cb_maxseq as unsafe extern "C" fn(*const sudo_defs_val) -> bool);

        /* Set iolog_user callback. */
        let fresh12 = &mut (*sudo_defs_table.as_mut_ptr().offset(I_IOLOG_USER)).callback;
        *fresh12 = Some(cb_iolog_user as unsafe extern "C" fn(*const sudo_defs_val) -> bool);

        /* Set iolog_group callback. */
        let fresh13 = &mut (*sudo_defs_table.as_mut_ptr().offset(I_IOLOG_GROUP)).callback;
        *fresh13 = Some(cb_iolog_group as unsafe extern "C" fn(*const sudo_defs_val) -> bool);

        /* Set iolog_mode callback. */
        let fresh14 = &mut (*sudo_defs_table.as_mut_ptr().offset(I_IOLOG_MODE)).callback;
        *fresh14 = Some(cb_iolog_mode as unsafe extern "C" fn(*const sudo_defs_val) -> bool);

        /* Set tty_tickets callback. */
        let fresh15 = &mut (*sudo_defs_table.as_mut_ptr().offset(I_TTY_TICKETS)).callback;
        *fresh15 = Some(cb_tty_tickets as unsafe extern "C" fn(*const sudo_defs_val) -> bool);

        /* Set umask callback. */
        let fresh16 = &mut (*sudo_defs_table.as_mut_ptr().offset(I_UMASK)).callback;
        *fresh16 = Some(cb_umask as unsafe extern "C" fn(*const sudo_defs_val) -> bool);

        /* It is now safe to use log_warningx() and set_perms() */
        if unknown_user {
            log_warningx(
                SLOG_SEND_MAIL,
                b"unknown uid: %u\0" as *const u8 as *const libc::c_char,
                sudo_user.uid,
            );
            debug_return_bool!(false);
        }

        /*
         * Set runas passwd/group entries based on command line or sudoers.
         * Note that if runas_group was specified without runas_user we
         * run the command as the invoking user.
         */
        if !runas_group.is_null() {
            if !set_runasgr(runas_group, false) {
                debug_return_bool!(false);
            }
            if !set_runaspw(
                if !runas_user.is_null() {
                    runas_user
                } else {
                    sudo_user.name
                },
                false,
            ) {
                debug_return_bool!(false);
            }
        } else if !set_runaspw(
            if !runas_user.is_null() {
                runas_user
            } else {
                def_runas_default!()
            },
            false,
        ) {
            debug_return_bool!(false);
        }

        /*} else {
            if !set_runaspw(
                if !runas_user.is_null() {
                    runas_user
                } else {
                    def_runas_default!()
                },
                false,
            ) {
                debug_return_bool!(false);
            }
        }*/

        debug_return_bool!(true);
    } //unsafe
}

/*
 * Fill in user_cmnd, user_args, user_base and user_stat variables
 * and apply any command-specific defaults entries.
 */
fn set_cmnd() -> libc::c_int {
    unsafe {
        let mut nss: *mut sudo_nss = std::ptr::null_mut::<sudo_nss>();
        let mut path: *mut libc::c_char = sudo_user.path;
        let mut ret: libc::c_int = FOUND;
        debug_decl!(SUDOERS_DEBUG_PLUGIN!());

        /* Allocate user_stat for find_path() and match functions. */
        sudo_user.cmnd_stat = calloc(
            1 as libc::c_int as libc::c_ulong,
            ::core::mem::size_of::<stat>() as libc::c_ulong,
        ) as *mut stat;
        if (sudo_user.cmnd_stat).is_null() {
            sudo_warnx!(
                b"%s: %s\0" as *const u8 as *const libc::c_char,
                get_function_name!(),
                b"unable to allocate memory\0" as *const u8 as *const libc::c_char
            );
            debug_return_int!(NOT_FOUND_ERROR);
        }

        /* Default value for cmnd, overridden below. */
        if (sudo_user.cmnd).is_null() {
            sudo_user.cmnd = *NewArgv.offset(0 as libc::c_int as isize);
        }

        if ISSET!(sudo_mode, MODE_RUN | MODE_EDIT | MODE_CHECK) != 0 {
            if ISSET!(sudo_mode, MODE_EDIT) == 0 {
                if !(def_secure_path!()).is_null() && !user_is_exempt() {
                    path = def_secure_path!();
                }
                if !set_perms(PERM_RUNAS) {
                    debug_return_int!(-(1 as libc::c_int))
                }
                ret = find_path(
                    *NewArgv.offset(0 as libc::c_int as isize),
                    &mut sudo_user.cmnd,
                    sudo_user.cmnd_stat,
                    path,
                    def_ignore_dot!(),
                    std::ptr::null::<*mut libc::c_char>(),
                );
                if !restore_perms() {
                    debug_return_int!(-(1 as libc::c_int))
                }
                if ret == NOT_FOUND {
                    /* Failed as root, try as invoking user. */
                    if !set_perms(PERM_USER) {
                        debug_return_int!(-(1 as libc::c_int))
                    }
                    ret = find_path(
                        *NewArgv.offset(0 as libc::c_int as isize),
                        &mut sudo_user.cmnd,
                        sudo_user.cmnd_stat,
                        path,
                        def_ignore_dot!(),
                        std::ptr::null::<*mut libc::c_char>(),
                    );
                    if !restore_perms() {
                        debug_return_int!(-(1 as libc::c_int))
                    }
                }
                if ret == NOT_FOUND_ERROR {
                    if *__errno_location() == ENAMETOOLONG {
                        audit_failure(
                            NewArgc,
                            NewArgv,
                            b"command too long\0" as *const u8 as *const libc::c_char,
                        );
                    }
                    log_warning(
                        0 as libc::c_int,
                        b"%s\0" as *const u8 as *const libc::c_char,
                        *NewArgv.offset(0 as libc::c_int as isize),
                    );
                    debug_return_int!(ret);
                }
            }

            /* set user_args */
            if NewArgc > 1 as libc::c_int {
                let mut to: *mut libc::c_char = std::ptr::null_mut::<libc::c_char>();
                let mut from: *mut libc::c_char = std::ptr::null_mut::<libc::c_char>();
                let mut av: *mut *mut libc::c_char = std::ptr::null_mut::<*mut libc::c_char>();
                let mut size: size_t = 0;
                let mut n: size_t = 0;

                /* Alloc and build up user_args. */
                av = NewArgv.offset(1 as libc::c_int as isize);
                while !(*av).is_null() {
                    size = (size as libc::c_ulong)
                        .wrapping_add((strlen(*av)).wrapping_add(1 as libc::c_int as libc::c_ulong))
                        as size_t as size_t;
                    av = av.offset(1);
                }
                if size == 0 as libc::c_int as libc::c_ulong || {
                    sudo_user.cmnd_args = malloc(size) as *mut libc::c_char;
                    (sudo_user.cmnd_args).is_null()
                } {
                    sudo_warnx!(
                        b"%s: %s\0" as *const u8 as *const libc::c_char,
                        get_function_name!(),
                        b"unable to allocate memory\0" as *const u8 as *const libc::c_char
                    );
                    debug_return_int!(-(1 as libc::c_int));
                }
                if ISSET!(sudo_mode, MODE_SHELL | MODE_LOGIN_SHELL) != 0
                    && ISSET!(sudo_mode, MODE_RUN) != 0
                {
                    /*
                     * When running a command via a shell, the sudo front-end
                     * escapes potential meta chars.  We unescape non-spaces
                     * for sudoers matching and logging purposes.
                     */
                    to = sudo_user.cmnd_args;
                    av = NewArgv.offset(1 as libc::c_int as isize);
                    loop {
                        from = *av;
                        if from.is_null() {
                            break;
                        }
                        while *from != 0 {
                            if *from.offset(0 as libc::c_int as isize) as libc::c_int == '\\' as i32
                                && *from.offset(1 as libc::c_int as isize) as libc::c_int
                                    != '\0' as i32
                                && isspace!(
                                    *from.offset(1 as libc::c_int as isize) as libc::c_uchar
                                        as libc::c_int as isize
                                ) == 0
                            {
                                from = from.offset(1);
                            }
                            if size
                                .wrapping_sub(to.offset_from(sudo_user.cmnd_args) as libc::c_long
                                    as libc::c_ulong)
                                < 1 as libc::c_int as libc::c_ulong
                            {
                                sudo_warnx!(
                                    b"internal error, %s overflow\0" as *const u8
                                        as *const libc::c_char,
                                    get_function_name!()
                                );
                                debug_return_int!(NOT_FOUND_ERROR);
                            }
                            from = from.offset(1);
                            to = to.offset(1);
                            *to = *from;
                        }
                        if size
                            .wrapping_sub(to.offset_from(sudo_user.cmnd_args) as libc::c_long
                                as libc::c_ulong)
                            < 1 as libc::c_int as libc::c_ulong
                        {
                            sudo_warnx!(
                                b"internal error, %s overflow\0" as *const u8
                                    as *const libc::c_char,
                                get_function_name!()
                            );
                            debug_return_int!(NOT_FOUND_ERROR);
                        }
                        let fresh19 = to;
                        to = to.offset(1);
                        *fresh19 = ' ' as i32 as libc::c_char;
                        av = av.offset(1);
                    }
                    to = to.offset(-1);
                    *to = '\0' as i32 as libc::c_char;
                } else {
                    to = sudo_user.cmnd_args;
                    av = NewArgv.offset(1 as libc::c_int as isize);
                    while !(*av).is_null() {
                        n = sudo_strlcpy(
                            to,
                            *av,
                            size.wrapping_sub(to.offset_from(sudo_user.cmnd_args) as libc::c_long
                                as libc::c_ulong),
                        );
                        if n >= size
                            .wrapping_sub(to.offset_from(sudo_user.cmnd_args) as libc::c_long
                                as libc::c_ulong)
                        {
                            sudo_warnx!(
                                b"internal error, %s overflow\0" as *const u8
                                    as *const libc::c_char,
                                get_function_name!()
                            );
                            debug_return_int!(-(1 as libc::c_int));
                        }
                        to = to.offset(n as isize);
                        let fresh20 = to;
                        to = to.offset(1);
                        *fresh20 = ' ' as i32 as libc::c_char;
                        av = av.offset(1);
                    }
                    to = to.offset(-1);
                    *to = '\0' as i32 as libc::c_char;
                }
            }
        }

        sudo_user.cmnd_base = strrchr(sudo_user.cmnd, '/' as i32);
        if !(sudo_user.cmnd_base).is_null() {
            sudo_user.cmnd_base = (sudo_user.cmnd_base).offset(1);
        } else {
            sudo_user.cmnd_base = sudo_user.cmnd;
        }

        nss = (*snl).tqh_first;
        while !nss.is_null() {
            if !update_defaults(
                (*nss).parse_tree,
                std::ptr::null_mut::<defaults_list>(),
                SETDEF_CMND,
                false,
            ) {
                log_warningx(
                    SLOG_SEND_MAIL | SLOG_NO_STDERR,
                    b"problem with defaults entries\0" as *const u8 as *const libc::c_char,
                );
            }
            nss = (*nss).entries.tqe_next;
        }

        debug_return_int!(ret);
    } //unsafe
}

/*
 * Open sudoers and sanity check mode/owner/type.
 * Returns a handle to the sudoers file or NULL on error.
 */
#[no_mangle]
pub fn open_sudoers(
    mut sudoers: *const libc::c_char,
    mut doedit: bool,
    mut keepopen: *mut bool,
) -> *mut FILE {
    let mut sb: stat = sb_all_arch;
    let mut fp: *mut FILE = std::ptr::null_mut::<FILE>();
    let mut perm_root: bool = false;
    unsafe {
        debug_decl!(SUDOERS_DEBUG_PLUGIN!());

        if !set_perms(PERM_SUDOERS) {
            debug_return_ptr!(std::ptr::null_mut::<FILE>());
        }

        'again: loop {
            match sudo_secure_file_v1(sudoers, sudoers_uid, sudoers_gid, &mut sb) {
                SUDO_PATH_SECURE => {
                    /*
                     * If we are expecting sudoers to be group readable by
                     * SUDOERS_GID but it is not, we must open the file as root,
                     * not uid 1.
                     */
                    if sudoers_uid == ROOT_UID as libc::c_uint
                        && ISSET!(sudoers_mode, S_IRGRP!()) != 0
                    {
                        /*if (ISSET!(sb.st_mode, S_IRGRP!()) == 0 || sb.st_gid != SUDOERS_GID as libc::c_uint) && !perm_root {
                            if !restore_perms() || !set_perms(PERM_ROOT) {
                                debug_return_ptr!(std::ptr::null_mut::<FILE>());
                            }
                        }*/

                        if (ISSET!(sb.st_mode, S_IRGRP!()) == 0
                            || sb.st_gid != SUDOERS_GID as libc::c_uint)
                            && !perm_root
                            && (!restore_perms() || !set_perms(PERM_ROOT))
                        {
                            debug_return_ptr!(std::ptr::null_mut::<FILE>());
                        }

                        /*if ISSET!(sb.st_mode, S_IRGRP!()) == 0
                            || sb.st_gid != SUDOERS_GID as libc::c_uint
                        {
                            /*if !perm_root {
                                if !restore_perms() || !set_perms(PERM_ROOT) {
                                    debug_return_ptr!(std::ptr::null_mut::<FILE>());
                                }
                            }*/
                             if !perm_root && (!restore_perms() || !set_perms(PERM_ROOT)) {
                                 debug_return_ptr!(std::ptr::null_mut::<FILE>());
                             }

                        }*/
                    }
                    /*
                     * Open sudoers and make sure we can read it so we can present
                     * the user with a reasonable error message (unlike the lexer).
                     */
                    fp = fopen(sudoers, b"r\0" as *const u8 as *const libc::c_char);
                    if fp.is_null() {
                        log_warning(
                            SLOG_SEND_MAIL,
                            b"unable to open %s\0" as *const u8 as *const libc::c_char,
                            sudoers,
                        );
                    } else if sb.st_size != 0 as libc::c_int as libc::c_long && fgetc(fp) == EOF {
                        log_warning(
                            SLOG_SEND_MAIL,
                            b"unable to read %s\0" as *const u8 as *const libc::c_char,
                            sudoers,
                        );
                        fclose(fp);
                        fp = std::ptr::null_mut::<FILE>();
                    } else {
                        /* Rewind fp and set close on exec flag. */
                        rewind(fp);
                        fcntl(fileno(fp), F_SETFD, 1 as libc::c_int);
                    }

                    /*} else {
                        if sb.st_size != 0 as libc::c_int as libc::c_long && fgetc(fp) == EOF {
                            log_warning(
                                SLOG_SEND_MAIL,
                                b"unable to read %s\0" as *const u8 as *const libc::c_char,
                                sudoers,
                            );
                            fclose(fp);
                            fp = std::ptr::null_mut::<FILE>();
                        } else {
                            /* Rewind fp and set close on exec flag. */
                            rewind(fp);
                            fcntl(fileno(fp), F_SETFD, 1 as libc::c_int);
                        }
                    }*/
                }
                SUDO_PATH_MISSING => {
                    /*
                     * If we tried to stat() sudoers as non-root but got EACCES,
                     * try again as root.
                     */
                    if !(*__errno_location() == EACCES && geteuid() != ROOT_UID as libc::c_uint) {
                        let mut serrno: libc::c_int = *__errno_location();
                        if restore_perms() {
                            if !set_perms(PERM_ROOT) {
                                debug_return_ptr!(std::ptr::null_mut::<FILE>());
                            }
                            perm_root = true;
                            continue 'again;
                        }
                        *__errno_location() = serrno;
                    }
                    log_warningx(
                        SLOG_SEND_MAIL,
                        b"unable to stat %s\0" as *const u8 as *const libc::c_char,
                        sudoers,
                    );
                }
                SUDO_PATH_BAD_TYPE => {
                    log_warningx(
                        SLOG_SEND_MAIL,
                        b"%s is not a regular file\0" as *const u8 as *const libc::c_char,
                        sudoers,
                    );
                }
                SUDO_PATH_WRONG_OWNER => {
                    log_warningx(
                        SLOG_SEND_MAIL,
                        b"%s is owned by uid %u, should be %u\0" as *const u8
                            as *const libc::c_char,
                        sudoers,
                        sb.st_uid,
                        sudoers_uid,
                    );
                }
                SUDO_PATH_WORLD_WRITABLE => {
                    log_warningx(
                        SLOG_SEND_MAIL,
                        b"%s is world writable\0" as *const u8 as *const libc::c_char,
                        sudoers,
                    );
                }
                SUDO_PATH_GROUP_WRITABLE => {
                    log_warningx(
                        SLOG_SEND_MAIL,
                        b"%s is owned by gid %u, should be %u\0" as *const u8
                            as *const libc::c_char,
                        sudoers,
                        sb.st_gid,
                        sudoers_gid,
                    );
                }
                _ => { /* NOTREACHED */ }
            }
            break;
        }

        if !restore_perms() {
            /* unable to change back to root */
            if !fp.is_null() {
                fclose(fp);
                fp = std::ptr::null_mut::<FILE>();
            }
        }

        debug_return_ptr!(fp);
    } //unsafe
}

fn set_loginclass(mut pw: *mut passwd) -> bool {
    true
}

/*
 * Look up the fully qualified domain name of host.
 * Use AI_FQDN if available since "canonical" is not always the same as fqdn.
 * Returns true on success, setting longp and shortp.
 * Returns false on failure, longp and shortp are unchanged.
 */
fn resolve_host(
    mut host: *const libc::c_char,
    mut longp: *mut *mut libc::c_char,
    mut shortp: *mut *mut libc::c_char,
) -> libc::c_int {
    let mut res0: *mut addrinfo = std::ptr::null_mut::<addrinfo>();
    let mut hint: addrinfo = addrinfo {
        ai_flags: 0,
        ai_family: 0,
        ai_socktype: 0,
        ai_protocol: 0,
        ai_addrlen: 0,
        ai_addr: std::ptr::null_mut::<sockaddr>(),
        ai_canonname: std::ptr::null_mut::<libc::c_char>(),
        ai_next: std::ptr::null_mut::<addrinfo>(),
    };
    let mut cp: *mut libc::c_char = std::ptr::null_mut::<libc::c_char>();
    let mut lname: *mut libc::c_char = std::ptr::null_mut::<libc::c_char>();
    let mut sname: *mut libc::c_char = std::ptr::null_mut::<libc::c_char>();
    let mut ret: libc::c_int = 0;
    unsafe {
        debug_decl!(SUDOERS_DEBUG_PLUGIN!());

        memset(
            &mut hint as *mut addrinfo as *mut libc::c_void,
            0 as libc::c_int,
            ::core::mem::size_of::<addrinfo>() as libc::c_ulong,
        );
        hint.ai_family = PF_UNSPEC;
        hint.ai_flags = AI_FQDN;

        ret = getaddrinfo(host, std::ptr::null::<libc::c_char>(), &hint, &mut res0);
        if ret != 0 as libc::c_int {
            debug_return_int!(ret);
        }
        lname = strdup((*res0).ai_canonname);
        if lname.is_null() {
            freeaddrinfo(res0);
            debug_return_int!(EAI_MEMORY);
        }
        cp = strchr(lname, '.' as i32);
        if !cp.is_null() {
            sname = strndup(lname, cp.offset_from(lname) as libc::c_long as size_t);
            if sname.is_null() {
                free(lname as *mut libc::c_void);
                freeaddrinfo(res0);
                debug_return_int!(EAI_MEMORY);
            }
        } else {
            sname = lname;
        }
        freeaddrinfo(res0);
        *longp = lname;
        *shortp = sname;

        debug_return_int!(0);
    } //unsafe
}

/*
 * Look up the fully qualified domain name of user_host and user_runhost.
 * Sets user_host, user_shost, user_runhost and user_srunhost.
 */
unsafe extern "C" fn cb_fqdn(mut sd_un: *const sudo_defs_val) -> bool {
    let mut remote: bool = false;
    let mut lhost: *mut libc::c_char = std::ptr::null_mut::<libc::c_char>();
    let mut shost: *mut libc::c_char = std::ptr::null_mut::<libc::c_char>();
    debug_decl!(SUDOERS_DEBUG_PLUGIN!());

    /* Nothing to do if fqdn flag is disabled. */
    if !sd_un.is_null() && (*sd_un).flag == 0 {
        debug_return_bool!(true);
    }

    /* If the -h flag was given we need to resolve both host and runhost. */
    remote = strcmp(sudo_user.runhost, sudo_user.host) != 0 as libc::c_int;

    /* First resolve user_host, setting user_host and user_shost. */
    if resolve_host(sudo_user.host, &mut lhost, &mut shost) != 0 as libc::c_int {
        let mut rc: libc::c_int = resolve_host(sudo_user.runhost, &mut lhost, &mut shost);
        if rc != 0 as libc::c_int {
            gai_log_warning(
                SLOG_SEND_MAIL | SLOG_RAW_MSG,
                rc,
                b"unable to resolve host %s\0" as *const u8 as *const libc::c_char,
                sudo_user.host,
            );
            debug_return_bool!(false);
        }
    }
    if sudo_user.shost != sudo_user.host {
        free(sudo_user.shost as *mut libc::c_void);
    }
    free(sudo_user.host as *mut libc::c_void);
    sudo_user.host = lhost;
    sudo_user.shost = shost;
    shost = std::ptr::null_mut::<libc::c_char>();

    /* Next resolve user_runhost, setting user_runhost and user_srunhost. */
    lhost = shost;
    if remote {
        if resolve_host(sudo_user.runhost, &mut lhost, &mut shost) == 0 {
            sudo_warnx!(
                b"unable to resolve host %s\0" as *const u8 as *const libc::c_char,
                sudo_user.runhost
            );
        }
    } else {
        /* Not remote, just use user_host. */
        lhost = strdup(sudo_user.host);
        if !lhost.is_null() {
            if sudo_user.shost != sudo_user.host {
                shost = strdup(sudo_user.shost);
            } else {
                shost = lhost;
            }
        }
        if lhost.is_null() || shost.is_null() {
            free(lhost as *mut libc::c_void);
            if lhost != shost {
                free(shost as *mut libc::c_void);
            }
            sudo_warnx!(
                b"%s: %s\0" as *const u8 as *const libc::c_char,
                get_function_name!(),
                b"unable to allocate memory\0" as *const u8 as *const libc::c_char
            );
            debug_return_bool!(false);
        }
    }
    if !lhost.is_null() && !shost.is_null() {
        if sudo_user.srunhost != sudo_user.runhost {
            free(sudo_user.srunhost as *mut libc::c_void);
        }
        free(sudo_user.runhost as *mut libc::c_void);
        sudo_user.runhost = lhost;
        sudo_user.srunhost = shost;
    }

    sudo_debug_printf!(
        SUDO_DEBUG_INFO | SUDO_DEBUG_LINENO,
        b"host %s, shost %s, runhost %s, srunhost %s\0" as *const u8 as *const libc::c_char,
        sudo_user.host,
        sudo_user.shost,
        sudo_user.runhost,
        sudo_user.srunhost
    );
    debug_return_bool!(true);
}

/*
 * Get passwd entry for the user we are going to run commands as
 * and store it in runas_pw.  By default, commands run as "root".
 */
fn set_runaspw(mut user: *const libc::c_char, mut quiet: bool) -> bool {
    let mut pw: *mut passwd = std::ptr::null_mut::<passwd>();
    unsafe {
        debug_decl!(SUDOERS_DEBUG_PLUGIN!());

        unknown_runas_uid = false;
        if *user as libc::c_int == '#' as i32 {
            let mut errstr: *const libc::c_char = std::ptr::null::<libc::c_char>();
            let mut uid: uid_t =
                sudo_strtoid_v2(user.offset(1 as libc::c_int as isize), &mut errstr);
            if errstr.is_null() {
                pw = sudo_getpwuid(uid);
                if pw.is_null() {
                    unknown_runas_uid = true;
                    pw = sudo_fakepwnam(user, sudo_user.gid);
                }
            }
        }
        if pw.is_null() {
            pw = sudo_getpwnam(user);
            if pw.is_null() {
                if !quiet {
                    log_warningx(
                        SLOG_RAW_MSG,
                        b"unknown user: %s\0" as *const u8 as *const libc::c_char,
                        user,
                    );
                }
                debug_return_bool!(false);
            }
        }
        if !(sudo_user._runas_pw).is_null() {
            sudo_pw_delref(sudo_user._runas_pw);
        }
        sudo_user._runas_pw = pw;
        debug_return_bool!(true);
    } //unsafe
}

/*
 * Get group entry for the group we are going to run commands as
 * and store it in runas_gr.
 */
fn set_runasgr(mut group: *const libc::c_char, mut quiet: bool) -> bool {
    let mut gr: *mut group = std::ptr::null_mut::<group>();
    unsafe {
        debug_decl!(SUDOERS_DEBUG_PLUGIN!());

        unknown_runas_gid = false;
        if *group as libc::c_int == '#' as i32 {
            let mut errstr: *const libc::c_char = std::ptr::null::<libc::c_char>();
            let mut gid: gid_t =
                sudo_strtoid_v2(group.offset(1 as libc::c_int as isize), &mut errstr);
            if errstr.is_null() {
                gr = sudo_getgrgid(gid);
                if gr.is_null() {
                    unknown_runas_gid = true;
                    gr = sudo_fakegrnam(group);
                }
            }
        }
        if gr.is_null() {
            gr = sudo_getgrnam(group);
            if gr.is_null() {
                if !quiet {
                    log_warningx(
                        SLOG_RAW_MSG,
                        b"unknown group: %s\0" as *const u8 as *const libc::c_char,
                        group,
                    );
                }
                debug_return_bool!(false);
            }
        }
        if !(sudo_user._runas_gr).is_null() {
            sudo_gr_delref(sudo_user._runas_gr);
        }
        sudo_user._runas_gr = gr;
        debug_return_bool!(true);
    } //unsafe
}

/*
 * Callback for runas_default sudoers setting.
 */
unsafe extern "C" fn cb_runas_default(mut sd_un: *const sudo_defs_val) -> bool {
    debug_decl!(SUDOERS_DEBUG_PLUGIN!());

    /* Only reset runaspw if user didn't specify one. */
    if runas_user.is_null() && runas_group.is_null() {
        debug_return_bool!(set_runaspw((*sd_un).str_0, true))
    }
    debug_return_bool!(true);
}

/*
 * Callback for tty_tickets sudoers setting.
 */
unsafe extern "C" fn cb_tty_tickets(mut sd_un: *const sudo_defs_val) -> bool {
    debug_decl!(SUDOERS_DEBUG_PLUGIN!());

    /* Convert tty_tickets -> timestamp_type */
    if (*sd_un).flag != 0 {
        def_timestamp_type!() = def_tuple::tty;
    } else {
        def_timestamp_type!() = def_tuple::global;
    }
    debug_return_bool!(true);
}

/*
 * Callback for umask sudoers setting.
 */
unsafe extern "C" fn cb_umask(mut sd_un: *const sudo_defs_val) -> bool {
    debug_decl!(SUDOERS_DEBUG_PLUGIN!());

    /* Force umask if explicitly set in sudoers. */
    force_umask = (*sd_un).mode != ACCESSPERMS!() as libc::c_uint;

    debug_return_bool!(true);
}

/*
 * Cleanup hook for sudo_fatal()/sudo_fatalx()
 */
#[no_mangle]
pub unsafe extern "C" fn sudoers_cleanup() {
    let mut nss: *mut sudo_nss = std::ptr::null_mut::<sudo_nss>();
    debug_decl!(SUDOERS_DEBUG_PLUGIN!());

    if !snl.is_null() {
        nss = (*snl).tqh_first;
        while !nss.is_null() {
            ((*nss).close).expect("non-null function pointer")(nss);
            nss = (*nss).entries.tqe_next;
        }
    }
    if !(def_group_plugin!()).is_null() {
        group_plugin_unload();
    }
    sudo_freepwcache();
    sudo_freegrcache();

    debug_return!();
}

fn create_admin_success_flag() -> libc::c_int {
    /* STUB */
    true as libc::c_int
}

fn tty_present() -> bool {
    unsafe {
        debug_decl!(SUDOERS_DEBUG_PLUGIN!());

        if (sudo_user.ttypath).is_null() {
            let mut fd: libc::c_int = open(_PATH_TTY!(), O_RDWR);
            if fd == -(1 as libc::c_int) {
                debug_return_bool!(false);
            }
            close(fd);
        }

        debug_return_bool!(true);
    } //unsafe
}
